﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Windows.Forms;
using PMC;
using PMC.Interfaces;
using PMC.Structs;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;

namespace CashCrusaderScript
{
    static class Webpage
    {
        #region Adminmessage

        /// <summary>
        /// Searches for admin messages, if found returns a Url to skip it
        /// </summary>
        /// <param name="webBrowser">Current webbrowser</param>
        /// <param name="url">Url to navigate to</param>
        /// <returns>System.Boolean representing if webbrowser should navigate to a new Uri</returns>
        public static bool SkipAdminMessage(IWbrowser webBrowser, out Uri url)
        {
            var document = webBrowser.Document;
            if (webBrowser.Url.ToString().IndexOf("adminmsg.php", StringComparison.OrdinalIgnoreCase) > -1)
            {
                foreach (var inputValue in document.DocumentNode.Descendants("input"))
                {
                    if ((inputValue.GetAttributeValue("type", String.Empty).Equals("radio") && inputValue.GetAttributeValue("name", String.Empty).Equals("option")) || (inputValue.GetAttributeValue("type", String.Empty).Equals("submit") && inputValue.GetAttributeValue("name", String.Empty).Equals("submit")))
                    {
                        //inputValue.InvokeMember("click"); TODO Not tested yet, 'cause not needed for now!
                        //return true;
                        NameValueCollection collection = HttpUtility.ParseQueryString(webBrowser.Url.Query);
                        collection.Add("submit", "Continue");
                        url = new UriBuilder(webBrowser.Url) {Query = collection.ToQueryString()}.Uri; // BUG? Should work! Not tested!
                        return true;
                    }
                }
            }
            url = null;
            return false;
        }

        #endregion

        #region Already Credited

        /// <summary>
        /// Checks for pages Uri's that contains HTML that suggests that you already received credit for visiting the page
        /// </summary>
        /// <param name="webBrowser">Current browser</param>
        /// <returns>System.Boolean representing wether the page has already been visited</returns>
        public static bool IsAlreadyCredited(IWbrowser webBrowser)
        {
            var document = webBrowser.Document;
            //Page already credited:
            int count = 0;
            foreach (var element in document.DocumentNode.Descendants("input"))
            {
                if (element.GetAttributeValue("value", String.Empty).Equals("LOGOUT", StringComparison.OrdinalIgnoreCase))
                    count++;
            }

            if (webBrowser.DocumentText.IndexOf("include(../pages/already_credited.php)", StringComparison.OrdinalIgnoreCase) > -1)
                count++; //Already_credited not included

            return count > 0;
        }

        #endregion

        #region Login

        private const string loginPath = "/pages/enter.php"; 
        private const string format = "username={0}&password={1}&autologin=1&ipsec=1&submit=Login";
        /// <summary>
        /// Performs a login on the current page
        /// </summary>
        /// <param name="website"></param>
        /// <param name="path"></param>
        public static void PerformLogin(Website website, string path = null)
        {
            if (website != null)
            {
                try
                {
                    var enterpage = new Uri(website.Webpage, path ?? loginPath);
                    var data = String.Format(CultureInfo.InvariantCulture, format, website.Username, website.Password);
                    using (Global.HtmlUtility.HttpWebRequest(enterpage, "POST", data));
                }
                catch (Exception e)
                {
                    Log.Instance.AddMessage(e);
                }
            }
            else
                Log.Instance.AddMessage("Trying to login, but no website was found!");//todo Login sometimes fail and doesn't return a thing it might be that no website was found like here OR HttpWebRequest made just above here freezes and stops functioning!
        }

        /// <summary>
        /// Cookies must contain the following strings!
        /// </summary>
        private static readonly string[] cookieRequirements = new[] { "autoipsec", "autousername", "autopassword" };

        /// <summary>
        /// Checks if the given webpage contains login-elements to test if login was succesfull
        /// </summary>
        /// <param name="webpage">String containing page HTML</param>
        /// <param name="cookies">Cookies of the document </param>
        /// <returns>Bool representing if login was succesfull</returns>
        public static bool IsLoggedIn(HtmlDocument webpage, CookieCollection cookies)
        {
            // If these cookies exists it means that you are logged in!
            int cookieCounter = 0;
            foreach (Cookie cookie in cookies)
            {
                if (cookieRequirements.Contains(cookie.Name))
                    cookieCounter++;
            }

            if (cookieCounter == cookieRequirements.Length)
                return true;

            var collection = webpage.DocumentNode.Descendants("input");
            int counter = 0;

            foreach (var htmlElement in collection)
            {
                if (counter == 2)
                    break;

                if (htmlElement.GetAttributeValue("name", String.Empty).Equals("password") && htmlElement.GetAttributeValue("type", String.Empty).IndexOf("password", StringComparison.OrdinalIgnoreCase) > -1)
                    counter++;
                if (htmlElement.GetAttributeValue("name", String.Empty).Equals("username") && htmlElement.GetAttributeValue("type", String.Empty).IndexOf("text", StringComparison.OrdinalIgnoreCase) > -1)
                    counter++;
            }

            return counter != 2;
        }
        #endregion

        /// <summary>
        /// Retrieves the collection as an Query string, suitable for Uri's
        /// </summary>
        /// <remarks>Extension Method</remarks>
        /// <param name="collection">NameValueCollection to convert</param>
        /// <returns>Query</returns>
        public static string ToQueryString(this NameValueCollection collection)
        {
            return "?" + String.Join("&", Array.ConvertAll(collection.AllKeys, key => String.Format(CultureInfo.InvariantCulture, "{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(collection[key]))));
        }
    }
}
